package com.h.trans.controller;

import com.h.trans.service.LogService;
import com.h.trans.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@Slf4j
@RequestMapping("/user2")
@RestController
public class UserController2 {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    /**
     * 程序正常执行，就会 提交事务
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("/r1")
    public String r1(String name,String password) {

        // 数据操作
        userService.registryUser(name,password);
        log.info("用户注册成功");


        return "注册成功";
    }

    /**
     * 程序出错，就会报错，进行回滚
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("/r2")
    public String r2(String name,String password) {

        userService.registryUser(name,password);
        log.info("用户注册成功");
        int a = 10 / 0;

        return "注册成功";
    }

    /**
     * 程序出现异常，但是进行内部处理，不进行抛出异常，就不会发生回滚操作，就会进行提交
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("/r3")
    public String r3(String name,String password) {

        userService.registryUser(name,password);
        log.info("用户注册成功");
        try {
            int a = 10 / 0;
        }catch (Exception e) {
            log.error("程序出现异常");
        }

        return "注册成功";
    }

    /**
     * 出现异常，进行手动回滚，或者在异常的时候抛出异常，就会进行回滚
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("/r4")
    public String r4(String name,String password) {

        userService.registryUser(name,password);
        log.info("用户注册成功");
        try {
            int a = 10 / 0;
        }catch (Exception e) {
            log.error("程序出现异常");
//            throw new RuntimeException(e); // 抛出异常，就会回滚
            //手动回滚，这样页面就不会出现报错信息
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

        return "注册成功";
    }

    /**
     * @Transactional异常回滚的类型默认为 Error 和 运行时异常
     * 别的类型不会进行回滚
     */
    @Transactional
    @RequestMapping("/r5")
    public String r5(String name,String password) throws IOException {

        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功 影响行数 = " + result);
        if(true) {
            throw new IOException();
        }

        return "注册成功";
    }

    /**
     * 想要别的 异常类型进行回滚，需要进行添加异常属性
     * @Transactional异常回滚的类型默认为 Error 和 运行时异常
     */
    @Transactional(rollbackFor = {IOException.class, RuntimeException.class, Error.class}) // 可以存放数组类型
    @RequestMapping("/r6")
    public String r6(String name,String password) throws IOException {

        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功 影响行数 = " + result);
        if(true) {
            throw new IOException();
        }

        return "注册成功";
    }


    /**
     * 事务的隔离级别，通过 isolation 进行设置
     * Isolation.READ_COMMITTED 读未提取
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    @RequestMapping("/r7")
    public String r7(String name,String password) {

        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功 影响行数 = " + result);
        return "注册成功";
    }

    /**
     * 事务传播机制
     * 默认为 REQUIRED
     */
    @Transactional()
    @RequestMapping("/r8")
    public String r8(String name,String password) {

        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功 影响行数 = " + result);
        Integer logResult = logService.insertLog(name,"用户注册");
        log.info("日志记录成功 影响行数 = " + logResult);

        return "注册成功";
    }

    /**
     * NESTED 和 REQUIRED的区别是 NESTED 可以局部进行回滚，而REQUIRED不能进行局部回滚
     */
}
